package com.niit.hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

/**
 * Date:2024/11/8
 * Author：Ys
 * Description:
 */
public class HBaseClient {

    //定义 配置对象
    private Configuration configuration;

    //定义连接对象
    private Connection connection;

    //定义操作者 具有管理员权限
    private Admin admin;


    //连接HBase 初始化
    @Before
    public void init() throws IOException {
        configuration = HBaseConfiguration.create();//创建配置对象
        connection = ConnectionFactory.createConnection(configuration);//创建连接对象
        admin = connection.getAdmin();//获取操作者
        System.out.println("连接 Habse Success");

    }

    //创建名称空间
    @Test
    public void createNamespace() throws IOException {
        //1.定义名称空间的名称
        NamespaceDescriptor.Builder builder = NamespaceDescriptor.create("NIIT2024");
        //2.操作者利用 builder 去创建名称空间
        admin.createNamespace(builder.build());
    }

    //判断表是否存在
    @Test
    public void isTableExist() throws IOException {
        //定义MOMO_CHAT名称空间下 MSG表                   //名称空间                //表名
        TableName tableName = TableName.valueOf("MOMO_CHAT","MSG");
        boolean isExist = admin.tableExists(tableName);
        System.out.println("该表是否存在："+isExist);
    }

    //创建一张表 该表名为WATER_BILL 包含一个列族 C1
    @Test
    public void createTable() throws IOException {
        //1.定义名称空间 表名 列族
        String namespace = "NIIT2024";
        String tableName = "NIITData";
        String columnFamily = "xiaoming";
        //2.判断表是否存在
        TableName tableName1 = TableName.valueOf(namespace,tableName);
        if(admin.tableExists(tableName1)){
            return; //如果表存在 直接结束方法
        }
        //3.创建 表的描述构建器 ---意图 创建表的意图
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tableName1);

        //4.创建 列族的描述构建器  ---意图  创建列族的意图
        ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily));

        //5.将列族描述构建器 进行创建   --- 将创建列族的意图 进行实现  真实的列族
        ColumnFamilyDescriptor columnZu = columnFamilyDescriptorBuilder.build();

        //6.将真实的列族  添加到 表的描述构建器中
        tableDescriptorBuilder.setColumnFamily(columnZu);//现在 这张意图 拥有了一个真实列族   后面我们只需要将意图表进行实现
        //7.将表的描述构建器进行创建  --- 将 创建表的意图 进行实现  真实的表
        TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
        //8.提交到 HBase中
        admin.createTable(tableDescriptor);
    }

    //修改表 修改C1的版本
    @Test
    public void modifyTable() throws IOException {
        //1.定义名称空间 表名 列族 版本
        String namespace = "BD2GUET2024";
        String tableName = "WATER_BILL";
        String columnFamily = "C1";
        int version = 5;

        TableName tableName1 = TableName.valueOf(namespace,tableName);
        //1.判断表是否存在
        if(!admin.tableExists(tableName1)){
            return; //如果表不存在 直接结束方法
        }

        //2.得到修改的表的描述  真实的表
        TableDescriptor descriptor = admin.getDescriptor(tableName1);

        //3.创建真实的表的描述构建器  -- - 在实际上 先提出修改的想法
        TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(descriptor);// 虚拟表

        //4.得到列族描述器        真实的列族
        ColumnFamilyDescriptor columnFamily1 = descriptor.getColumnFamily(Bytes.toBytes(columnFamily));

        //5.得到 列族描述构建器  -- - 在实际上 先提出修改的想法
        ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(columnFamily1);

        //6.设置新的版本
        columnFamilyDescriptorBuilder.setMaxVersions(version);

        //7.修改好的列族描述构建器 进行创建 再提交给表的描述构建器
        tableDescriptorBuilder.modifyColumnFamily(columnFamilyDescriptorBuilder.build());

        //8.提交修改
        admin.modifyTable(tableDescriptorBuilder.build());
    }

    @Test
    public void dropTable() throws IOException {
        //1.定义名称空间 表名 列族 版本
        String namespace = "BD2GUET2024";
        String tableName = "WATER_BILL";

        TableName tableName1 = TableName.valueOf(namespace, tableName);

        //判断表是否存在，如果存在就删除
        if(admin.tableExists(tableName1)){
            admin.disableTable(tableName1);

            admin.deleteTable(tableName1);
        }
    }

    //添加数据
    @Test
    public void addData() throws IOException {

        //1.定义名称空间 表名 列族 版本
        String namespace = "NIIT2024";
        String tableName = "NIITData";
        String columnFamily = "xiaoming";
        String rowKey = "1001";
        String column = "shuai";
        String value = "就完了";

        //2.构建 put对象  --》put命令
        Put put = new Put(Bytes.toBytes(rowKey));

        //3.添加 列族 列 列值
        put.addColumn(  Bytes.toBytes(columnFamily),Bytes.toBytes(column),Bytes.toBytes(value)    );

        //4.使用HBase连接获取Table
        TableName tableName1 = TableName.valueOf(namespace, tableName);
        Table table = connection.getTable(tableName1);

        table.put(put);
        table.close();

    }
    //根据RowKey查询数据
    @Test
    public void getDataByRowKey() throws IOException {
        //1.定义名称空间 表名 列族 版本
        String namespace = "NIIT2024";
        String tableName = "NIITData";
        String rowKey = "1001";

        //2.使用HBase连接获取Table
        TableName tableName1 = TableName.valueOf(namespace, tableName);
        Table table = connection.getTable(tableName1);

        //3.构建一个查询对象
        Get get = new Get(Bytes.toBytes(rowKey));
        //4.利用已经创建好的 可操作的表进行查询
        Result result = table.get(get);// result是一个结果集 里面有很多列族 很多数据
        //5.通过结果集获得当前的Rowkey
        System.out.println("rowKey===>"+ Bytes.toString(result.getRow()) );
        //6.通过结果集获得所有的单元格
        List<Cell> cells = result.listCells();
        //7.遍历所有单元格 ，获得每个单元格中的信息
        for (Cell celll : cells){
            System.out.println( "列族："+ Bytes.toString(  celll.getFamilyArray(),  celll.getFamilyOffset(),  celll.getFamilyLength()   )   );

            System.out.println( "列名："+ Bytes.toString(  celll.getQualifierArray(),  celll.getQualifierOffset(),  celll.getQualifierLength() ) );

            System.out.println( "列值："+ Bytes.toString(  celll.getValueArray(),  celll.getValueOffset(),  celll.getValueLength()   )   );
        }
        //8.关闭表
        table.close();

    }

    //删除数据
    @Test
    public void deleteData() throws IOException {
        //1.定义名称空间 表名 列族 版本
        String namespace = "NIIT2024";
        String tableName = "NIITData";
        String rowKey = "1001";

        //2.使用HBase连接获取Table
        TableName tableName1 = TableName.valueOf(namespace, tableName);
        Table table = connection.getTable(tableName1);

        //3.创建一个删除对象
        Delete delete = new Delete(Bytes.toBytes(rowKey));

        //4.删除指定的列族:列
        delete.addColumn(Bytes.toBytes("xiaoming"),Bytes.toBytes("NAME"));

        //5.执行delete操作
        table.delete(delete);

        //6.关闭表
        table.close();
    }

    //扫描 MOMO_CHAT:MSG表
    @Test
    public void scanData() throws IOException {
        String namespace = "NIIT2024";
        String tableName = "NIITData";

        TableName tableName1 = TableName.valueOf(namespace, tableName);
        Table table = connection.getTable(tableName1);

        //1.构建Scan对象
        Scan scan = new Scan();
        scan.setLimit(50);

        //2.根据table 对象进行查询
        ResultScanner scanner = table.getScanner(scan);// ResultScanner 记录了多行数据 Result 一行数据

        for (Result result : scanner){
            List<Cell> cells = result.listCells();
            for (Cell celll : cells){

                System.out.println( "列族："+ Bytes.toString(  celll.getFamilyArray(),  celll.getFamilyOffset(),  celll.getFamilyLength()   )   );

                System.out.println( "列名："+ Bytes.toString(  celll.getQualifierArray(),  celll.getQualifierOffset(),  celll.getQualifierLength() ) );

                System.out.println( "列值："+ Bytes.toString(  celll.getValueArray(),  celll.getValueOffset(),  celll.getValueLength()   )   );
            }
        }
    }



    //关闭连接 释放资源
    @After
    public void close() throws IOException {
        admin.close();//关闭操作者
        connection.close();//关闭连接对象
        System.out.println("关闭 HBase 连接");
    }


}
